﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.WebControls;
using System.Xml.Linq;
using System.Reflection;
using Slam.Internal;
using Microsoft.SharePoint;
using Slam.Configuration;
using Slam.SharePoint;
using System.Threading;
using System.Web;

namespace Slam.FieldTypes
{
	public class SlamFieldControl : BaseFieldControl
	{
		public string Actions 
		{ 
			get;
			set;
		}

		public string CustomProperties 
		{ 
			get; 
			set; 
		}

		protected override void OnLoad(EventArgs e)
		{
			base.OnLoad(e);

			XDocument actions = XDocument.Parse(Actions);
			SlamFieldActionContext context = new SlamFieldActionContext();
			if (List.Fields.ContainsFieldWithStaticName("SLAM_x0020_ID") && ListItem["SLAM_x0020_ID"] != null)
			{
				context.SlamId = Convert.ToString(ListItem["SLAM_x0020_ID"]);
			}
			
			context.ListItemId = ItemId;
			context.FormUrl = Context.Request.Url.ToString();
			context.Field = Field;
			context.FieldControl = this;

			SPSecurity.RunWithElevatedPrivileges(delegate()
			{
				//GetSlamConfiguredType traverses entire site collection, use elevated privileges
				//to perform this operation
				using (SPSite elevatedSite = new SPSite(Web.Site.ID))
				{
					using (SPWeb elevatedWeb = elevatedSite.AllWebs[Web.ID])
					{
						SPList elevatedList = elevatedWeb.Lists[ListId];
						SPListItem elevatedListItem = elevatedList.Items.Add();
						elevatedListItem["ContentTypeId"] = Item["ContentTypeId"];

						SlamContext.Get(elevatedList).Actions.Register("ConfiguredPreSaveEvents" + FieldName, SlamEvent.PreSave, listItem =>
						{
							ExecuteActions(actions, SlamFieldActionType.PreSave, context);
						});

						SlamContext.Get(elevatedList).Actions.Register("ConfiguredPostSaveEvents" + FieldName, SlamEvent.PostSave, listItem =>
						{
							ExecuteActions(actions, SlamFieldActionType.PostSave, context);
						});
					}
				}
			});

			if (!String.IsNullOrEmpty(Actions))
				ExecuteActions(actions, SlamFieldActionType.Load, context);
		}

		private void ExecuteActions(XDocument actions, SlamFieldActionType type, SlamFieldActionContext context)
		{
			
			var matchedActions = (from actionElement in actions.Root.Elements()
								  where actionElement.Attribute("ActionType").Value == type.ToString()
								  orderby int.Parse(actionElement.Attribute("ExecutionOrder").Value) ascending
								  select actionElement);

			foreach (XElement action in matchedActions)
			{
				object actionObject = Type.GetType(action.Attribute("Class").Value).CreateInstance<object>();
				if (action.Attribute("Synchronous") != null && bool.Parse(action.Attribute("Synchronous").Value))
					actionObject.GetType().InvokeMember(action.Attribute("Method").Value, BindingFlags.Default | BindingFlags.InvokeMethod, null, actionObject, new object[] { context });
				else
				{
					Thread runThread = new Thread((actionContext) =>
						{
							actionObject.GetType().InvokeMember(action.Attribute("Method").Value, BindingFlags.Default | BindingFlags.InvokeMethod, null, actionObject, new object[] { actionContext });
						});
					runThread.Start(context);
				}
			}
		}
	}
}
